module ActionView
  module Helpers
    module PrototypeHelper
      CALLBACKS    = Set.new([:complete, :start, :cancel] +
                       (100..599).to_a)
      class JavaScriptGenerator
        private
        module GeneratorMethods
          # Shows hidden DOM elements with the given +ids+.
          def show(*ids)
            loop_on_multiple_args "show()", ids
          end

          # Hides the visible DOM elements with the given +ids+.
          def hide(*ids)
            loop_on_multiple_args "hide()", ids
          end
          
          # Slide Effect
          def slide(mode, id, options={})
            function =  "new Fx.Slide(#{id.to_json}, #{parse_transition_options(options.to_json)}).slide"
            function << "#{mode.to_s.capitalize}()"
            record(function)
          end
          
          private
            def parse_transition_options(javascript_hash)
              javascript_hash.gsub(/(.*)transition: "(.*)"(.*)/,'\1transition: \2\3')
            end
            
            def loop_on_multiple_args(method, ids)
              record(ids.size>1 ? 
                "#{javascript_object_for(ids)}.each(function(element){$(element).#{method};})" : 
                "$(#{ids.first.to_json}).#{method}")
            end
        end # End GeneratorMethods
      end



      def remote_function(options)
        javascript_options = options_for_ajax(options)

        function = "new Ajax("

        url_options = options[:url]
        url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash)
        function << "'#{url_for(url_options)}'"
        function << ", #{javascript_options}).request()"

        function = "#{options[:before]}; #{function}" if options[:before]
        function = "#{function}; #{options[:after]}"  if options[:after]
        function = "if (#{options[:condition]}) { #{function}; }" if options[:condition]
        function = "if (confirm('#{escape_javascript(options[:confirm])}')) { #{function}; }" if options[:confirm]

        return function
      end

      def form_remote_tag(options = {}, &block)
        options[:html] ||= {}
        options[:html][:onsubmit] = 
        (options[:html][:onsubmit] ? options[:html][:onsubmit] + "; " : "") + 
        "this.send(#{options_for_ajax(options)}); return false;"

        form_tag(options[:html].delete(:action) || url_for(options[:url]), options[:html], &block)
      end


      protected

      def options_for_ajax(options)
        js_options = build_callbacks(options)

        js_options['method']       = method_option_to_s(options[:method]) if options[:method]
        js_options['evalScripts']  = options[:script].nil? || options[:script]
        js_options['update']       = "$('#{options[:update]}')" if options[:update]

        options_for_javascript(js_options)
      end
    end
  end
end
